# -*- coding: iso-8859-15 -*-
"@author: Benoit L.-Dufresne"

import random
import math

class Camera(object):
    def __init__(self,x=0,y=0,z=-200, roll=0, yaw=0, pitch=0):
        self.x = x
        self.y = y
        self.z = z
        self.roll = roll    #Roll: tourner autour de l'axe z (se toucher l'epaule avec les oreilles
        self.yaw = yaw      #Yaw: tourner autour de l'axe y (faire non avec la tete)
        self.pitch = pitch  #Pitch: tourner autour de l'axe x (regarder en haut, regarder en bas)
        self.oeil = Point(200,200,300)
        self.milieu = Point(0,0,0)
        ##L'oeil sert de reference pour la transposition des coordonnees sur l'ecran
        
    def centrerOeil(self, hauteur, largeur):
        self.oeil.x = largeur/2
        self.oeil.y = hauteur/2
        
    def rouler(self, angle):
        self.roll += angle
        ##Axe des Z -> Ne devrait pas etre utile pour galax, on devrait pouvoir se contenter de pitch et yaw
        
    def pitcher(self, angle):
        
        x2 = self.x - self.milieu.x
        y2 = self.y - self.milieu.y
        z2 = self.z - self.milieu.z
        #        x = math.sin(angle)*z + math.cos(angle)*x
        #        z = math.cos(angle)*z - math.sin(angle)*x
        
        x = x2
        y = y2 * math.cos(-angle) - z2 * math.sin(-angle)
        z = y2 * math.sin(-angle) + z2 * math.cos(-angle)
        
        x2 = z * math.sin(0) + x * math.cos(0)
        y2 = y
        z2 = z * math.cos(0) - x * math.sin(0)
        
        x = y2 * math.sin(0) + x2 * math.cos(0)
        y = y2 * math.cos(0) - x2 * math.sin(0)
        z = z2;
        
        self.x = x+self.milieu.x
        self.y = y+self.milieu.y
        self.z = z+self.milieu.z
        self.pitch += angle
        ##Axe des X
        
    def yawer(self, angle):
        #On applique ensuite les rotations sur les points pour avoir leur position relative
        #a la camera qui a peut-etre effectue une rotation
        
        x2 = self.x - self.milieu.x
        y2 = self.y - self.milieu.y
        z2 = self.z - self.milieu.z
        #        x = math.sin(angle)*z + math.cos(angle)*x
        #        z = math.cos(angle)*z - math.sin(angle)*x
        
        x = z2 * math.sin(-angle) + x2 * math.cos(-angle)
        y = y2
        z = z2 * math.cos(-angle) - x2 * math.sin(-angle)
        
        x2 = x
        y2 = y * math.cos(0) - z * math.sin(0)
        z2 = y * math.sin(0) + z * math.cos(0)
        
        x = y2 * math.sin(0) + x2 * math.cos(0)
        y = y2 * math.cos(0) - x2 * math.sin(0)
        z = z2;
        
        self.x = x+self.milieu.x
        self.y = y+self.milieu.y
        self.z = z+self.milieu.z
        self.yaw += angle
        ##Axe des Y
        
    ##Fonction pour bouger la camera
    def bougerX(self, mouvement):
        x = 0 * math.sin(-self.yaw) + mouvement * math.cos(-self.yaw)
        y = 0
        z = 0 * math.cos(-self.yaw) - mouvement * math.sin(-self.yaw)
        
        x2 = x
        y2 = y * math.cos(-self.pitch) - z * math.sin(-self.pitch)
        z2 = y * math.sin(-self.pitch) + z * math.cos(-self.pitch)
        
        x = y2 * math.sin(-self.roll) + x2 * math.cos(self.roll)
        y = y2 * math.cos(-self.roll) - x2 * math.sin(-self.roll)
        z = z2;
        
        self.x += x
        self.y += y
        self.z += z
        
    def bougerY(self, mouvement):
        x2 = 0
        y2 = mouvement * math.cos(-self.pitch) - 0 * math.sin(-self.pitch)
        z2 = mouvement * math.sin(-self.pitch) + 0 * math.cos(-self.pitch)
        
        x = z2 * math.sin(-self.yaw) + x2 * math.cos(-self.yaw)
        y = y2
        z = z2 * math.cos(-self.yaw) - x2 * math.sin(-self.yaw)

        x = y2 * math.sin(-self.roll) + x2 * math.cos(-self.roll)
        y = y2 * math.cos(-self.roll) - x2 * math.sin(-self.roll)
        z = z2;
        
        self.x += x
        self.y += y
        self.z += z
        
    def bougerZ(self, mouvement):
        x = mouvement * math.sin(-self.yaw) + 0 * math.cos(-self.yaw)
        y = 0
        z = mouvement * math.cos(-self.yaw) - 0 * math.sin(-self.yaw)
        
        x2 = x
        y2 = y * math.cos(-self.pitch) - z * math.sin(-self.pitch)
        z2 = y * math.sin(-self.pitch) + z * math.cos(-self.pitch)
        
        x = y2 * math.sin(-self.roll) + x2 * math.cos(-self.roll)
        y = y2 * math.cos(-self.roll) - x2 * math.sin(-self.roll)
        z = z2;
        
        self.x += x
        self.y += y
        self.z += z
        
    def zoom(self, zoom):
        self.oeil.z += zoom

    

        
class Point(object):
    def __init__(self, x=0, y=0, z=0):
        self.x = x
        self.y = y
        self.z = z

        
def toEcran(camera, cercles):
    #les cercles sont une liste de points ou d'objets ayant des attributs x,y et z
    liste = toCamera(camera, cercles)
    for cercle in liste:
       cercle.x = (camera.oeil.x + cercle.x*camera.oeil.z/(cercle.z+camera.oeil.z))
       cercle.y = (camera.oeil.y - cercle.y*camera.oeil.z/(cercle.z+camera.oeil.z))

    return liste
        
def toCamera(camera, cercles):
    liste=[]
    for cercle in cercles:
        #pour chaque point, on effectue une translation pour avoir la position de la
        #camera comme origine
        x2 = cercle.x - camera.x
        y2 = cercle.y - camera.y
        z2 = cercle.z - camera.z
        
        #ensuite pour chaque point, on effectue une rotation pour avoir leur position
        #relative a la camera qui a peut-etre effectue une rotation
        x = z2 * math.sin(camera.yaw) + x2 * math.cos(camera.yaw)
        y = y2
        z = z2 * math.cos(camera.yaw) - x2 * math.sin(camera.yaw)
        
        x2 = x
        y2 = y * math.cos(camera.pitch) - cercle.z * math.sin(camera.pitch)
        z2 = y * math.sin(camera.pitch) + cercle.z * math.cos(camera.pitch)
        
        x = y2 * math.sin(camera.roll) + x2 * math.cos(camera.roll)
        y = y2 * math.cos(camera.roll) - x2 * math.sin(camera.roll)
        z = z2;
        if z > 0:
            liste.append(Point(x,y,z))
    return liste